/**
 * Title: 视口
 * 有时，您只想为迷你地图之类的内容渲染屏幕的一部分。使用视口可以控制屏幕上的渲染位置。
 */
#include <SDL_render.h>
#include <SDL_video.h>
#define SDL_MAIN_HANDLED
extern "C" {
#include <SDL.h>
#include <SDL_image.h>
}
#include <stdio.h>
#include <thread>
#include <chrono>
#include <string>
#include <vector>
#include <map>

const int SCREEN_WIDTH = 1280;
const int SCREEN_HEIGHT = 720;

#define sdlerror() { printf("error in line %d %s\n", __LINE__, SDL_GetError()); exit(-1); }
static void xthread_func(SDL_Window* window, SDL_Renderer* render, SDL_Texture *texture);
static void xtest();
int main(int argc, char *argv[])
{
    const char* filename = "1.png";
    if (argc > 1) {
        filename = argv[1];
    }
    // 初始化
    if(SDL_Init(SDL_INIT_VIDEO) < 0) sdlerror();

    // 在 SDL_Init 之后，创建渲染器之前设置
    /*
    "0": 禁用（最近邻插值，最快但质量差）
    "1" 或 "linear": 启用线性插值（平滑缩放）
    "2" 或 "best": 最佳质量（某些后端支持更高阶过滤）
    */
    SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1");
    // 或者使用字符串 "linear"
    // SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
        
    // 创建窗口和渲染器
    SDL_Window *window = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, 
        SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
    SDL_Renderer* render = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);

    // 初始化 IMG 为 支持 PNG
    if(IMG_Init(IMG_INIT_PNG) != IMG_INIT_PNG) 
        sdlerror();
    // 加载图片
    SDL_Surface *pngSurface = IMG_Load(filename);
    if(pngSurface == NULL) 
        sdlerror();
#if 01
    SDL_Rect rect { 0, 0, pngSurface->w, pngSurface->h };
    SDL_RenderSetViewport(render, &rect);
    printf("img w: %d, h: %d\n", rect.w - rect.x, rect.h - rect.y);
#endif        
    // 从图片图层中创建纹理
    SDL_Texture *texture = SDL_CreateTextureFromSurface(render , pngSurface );
    SDL_FreeSurface( pngSurface );
    pngSurface = NULL;

    //清屏
    SDL_SetRenderDrawColor( render, 0x00, 0xFF, 0xFF, 0xFF );
    SDL_RenderClear( render );
    // 将纹理拷贝到渲染器
    SDL_RenderCopy( render, texture, NULL, NULL );
    SDL_RenderPresent( render );

    //std::thread t(xthread_func, window, render, texture);

    SDL_Event event { 0 };
    while( SDL_PollEvent( &event ) != 0 || event.type != SDL_QUIT) {
        if (event.type <= SDL_RENDER_DEVICE_RESET) {
            //printf("event.type: %d\n", event.type);
        }

        if (event.type == SDL_WINDOWEVENT) {
            //printf("  SDL_WINDOWEVENT window.event: %d\n", event.window.event);
            if (event.window.event == SDL_WINDOWEVENT_RESIZED)  {
                SDL_Rect rect { 0 };
                SDL_RenderGetViewport(render, &rect);                
                SDL_RenderClear( render );
                SDL_RenderCopy(render, texture, nullptr, nullptr);
                SDL_RenderPresent( render );
                printf("  resize: wxh = %dx%d, v.wxh: %dx%d\n", event.window.data1, event.window.data2, rect.w, rect.h);
            }
        } else if (event.type == SDL_KEYDOWN) {
            printf("Key pressed: %d\n", event.key.keysym.sym);
            int opcode = 0;
            switch(event.key.keysym.sym) {
                case SDLK_DOWN:
                    opcode -= 20;
                    break;
                case SDLK_UP:
                    opcode += 20;
                    break;
                default:
                    break;
            }
            if ( 0 != opcode ) {
                static SDL_Rect rect = { 0 };
                static bool init = false;
                if (!init) {
                    SDL_RenderGetViewport(render, &rect);
                    init = true;
                }
                rect.x += opcode;
                rect.y += opcode;
                rect.w += opcode;
                rect.h += opcode;
                //SDL_RenderSetViewport(render, &rect);
                SDL_RenderClear( render );
                SDL_RenderCopy(render, texture, &rect, nullptr);
                SDL_RenderPresent( render );

                int w, h;
                SDL_GetWindowSize(window, &w, &h);
                printf("key press, w.wxh: %dx%d, v.wxh: %dx%d, \n", w, h, rect.w, rect.h);
            }            
        }
        event.type = 0;
    }

    //t.join();
    SDL_DestroyTexture( texture );
    SDL_DestroyRenderer( render );
    SDL_DestroyWindow(window);
    IMG_Quit();
    SDL_Quit();
    return 0;
}

void xthread_func(SDL_Window* window, SDL_Renderer* render, SDL_Texture *texture) {
    for (int i = 0; i < 10; ++i) {
        std::this_thread::sleep_for(std::chrono::seconds(5));
        static int w = SCREEN_WIDTH, h = SCREEN_HEIGHT;
        //SDL_GetWindowSize((SDL_Window*)window, &w, &h);
        if ( w > 10 || h > 10) {
            w += 50;
            h += 50;
        }
        SDL_SetWindowSize((SDL_Window*)window, w, h);
        /*
        SDL_Rect rect { 0, 0, w, h };
        SDL_RenderSetViewport(render, &rect);
        */
        SDL_RenderClear( render );
        SDL_RenderCopy(render, texture, nullptr, nullptr);
        SDL_RenderPresent( render );

        SDL_Rect rect { 0 };
        SDL_RenderGetViewport(render, &rect);
        printf("%s wxh: %dx%d\n", __func__, w, h);
        printf("    rect: x: %d, y: %d, w: %d, h: %d\n", rect.x, rect.y, rect.w, rect.h);
    }
}